/*
 * Copyright 2000-2020 ALPHA LAB.Inc All Rights Reserved.
 */
package com.alphalab.framework.util;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import com.alphalab.framework.log.IMoLog;
import com.alphalab.framework.log.MoLogFactory;

/**
 * 反射工具类.
 * @author allen 
 * @version 1.0.0 2018年3月5日
 */
public final class ReflectionUtil {
	
	/**
	 * logger.
	 */
	private static final IMoLog logger = MoLogFactory.getLog(ReflectionUtil.class);

	/**
	 * 私有构造函数.
	 */
	private ReflectionUtil() { 
	}
	
	 
	/**
	 * 按照类名反射出它的一个对象.
	 * @param className 包名+类名
	 * @return Object
	 */
	public static Object getObjByClassName(final String className) {
		Object obj = null;
		if (className != null) {
			try {
				final Class a = Class.forName(className);
				obj = a.newInstance();
			} catch (Exception ex) {
				logger.error("Class.forName异常", ex);
			}
		}
		return obj;
	}
		
	/**
	 * 按照类名,参数值反射出它的一个对象.
	 * @param className 包名+类名
	 * @param parameter 构造函数的参数值
	 * @return Object
	 */
	public static Object getObjByClassNameAndParameter(final String className, final Object[] parameter) {
		Object obj = null;
		if (className != null) {
			try {
				final Class a = Class.forName(className);
				final Constructor con = a.getConstructor(getParameterClass(parameter));
				obj = con.newInstance(parameter);				
			} catch (Exception ex) {
				logger.error("Class.forName.getConstructor异常", ex);
			}
		}
		return obj;
	}
	
	
	/**
	 * 用对象反射调用它的某个方法(指定参数类型的方法.
	 * @param className 类名
	 * @param obj 对象
	 * @param methodName 方法名
	 * @param parameter  参数数组
	 * @param methodParameters 参数类型数组
	 * @return Object
	 */
	public static  Object invokeMethodWithObjHasSpecialParame(final String className, 
			 final Object obj, final String methodName,
			 final Object[] parameter, final Class[] methodParameters) {
		Object object = null;
		try {
			final Method method = Class.forName(className).getMethod(methodName.trim(), methodParameters);
			object = method.invoke(obj, parameter);
		} catch (Exception ex) {
			logger.error("Class.forName.getMethod异常", ex);
		}
		return object;
	}

	/**
	 * 获取属性类型.
	 * @param clazz 类型
	 * @param propertyName 属性名称
	 * @return class
	 */
	public static Class<?> getProperType(final Class<?> clazz, final String propertyName) {
		final PropertyDescriptor pd = getPropertyDescriptor(clazz, propertyName);
		return pd.getPropertyType();
	}
	

	/**
	 * 获取属性值.
	 * @param obj 对象
	 * @param propertyName 属性名称
	 * @return 属性的值
	 */
	public static Object getPropertyValue(final Object obj, final String propertyName) {
		Object result = null;
		try {
			final PropertyDescriptor pd = getPropertyDescriptor(obj.getClass(), propertyName);
			if (pd != null) {
				final Method readMethod = pd.getReadMethod();
				result = readMethod.invoke(obj);
			}
		} catch (Exception ex) {
			logger.error("getPropertyValue异常", ex);
		}
		return result;
	}

	/**
	 * 设置属性值,将getterPropertyName 获取的值设置到setterPropertyName属性中.
	 * @param obj 对象
	 * @param propertyName 属性名称
	 * @param num 排序值
	 */
	public static void setPropertyValue(final Object obj, final String propertyName, final int num) {
		try {
			final PropertyDescriptor writePd = getPropertyDescriptor(obj.getClass(), propertyName); 
			if (writePd != null) {
				final Method writeMethod = writePd.getWriteMethod();	  
				writeMethod.invoke(obj, num);
			}
		} catch (Exception ex) {
			logger.error("setPropertyValue异常", ex);
		}
	}
		
	/**
	 * 获取对象中定义属性.
	 * @param clazz 对象class
	 * @param paramName 属性名称，可以是大写或小写
	 * @return 属性
	 */
	public static PropertyDescriptor getPropertyDescriptor(final Class<?> clazz, final String paramName) {
		PropertyDescriptor pd = null;
		String propertyName = paramName;
		try {
			final Field[] fields = clazz.getDeclaredFields();
			for (Field field : fields) {
				field.setAccessible(true);
				final String name = field.getName();
				if (name.toUpperCase().equals(paramName) || name.toLowerCase().equals(paramName)) {
					propertyName = name;
					break;
				}
			}
			if (propertyName != null) {
				pd = new PropertyDescriptor(propertyName, clazz);
			}
			
		} catch (Exception ex) {
			logger.error("getPropertyDescriptor异常", ex);
		}
		return pd;
	} 
	
	/**
	 * 获取参数列表的class对象.
	 * @param parameter 参数值数组
	 * @return Class[]
	 */
	private static Class[] getParameterClass(final Object[] parameter) {
		Class[] methodParameters = null;
		if (parameter != null && parameter.length > 0) {
			methodParameters = new Class[parameter.length];
			for (int i = 0, len = parameter.length; i < len; i++) {
				methodParameters[i] = parameter[i].getClass();
			}
		}
		return methodParameters;
	} 
	
}
